package com.lry.util;

import cn.hutool.json.JSONUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;

/**
 * @program: mybatisproject2
 * @description: 反射工具
 * @author: 李瑞益
 * @create: 2018-11-01 19:50
 **/
public class ReflectUtil {

    public static Field[] getAllFields(Object object){
        Class clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null){
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

    /**
     * 根据类名、方法名和注解类型获取方法上的注解
     * @param className 类全名
     * @param methodName 方法名
     * @param annotationClass 注解类
     * @return 注解对象 (可能为null）
     */
    public static Annotation getMethodAnnotaionByClassName(String className, String methodName, Class annotationClass){
        try {
            Class<?> aClass = Class.forName(className);
            //获取功能方法集合
            Method[] methods = aClass.getMethods();
            for(Method m : methods){
                if(m.getName().equals(methodName)){
                    Annotation annotation = m.getAnnotation(annotationClass);
                    if(annotation != null){
                        return annotation;
                    }
                    break;
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取属性上的注解
     * @param field 属性对象
     * @param c 注解类
     * @return 注解对象（可能为null）
     */
    public static Annotation getAnnotation(AccessibleObject field, Class c){
        Annotation annotation = field.getAnnotation(c);
        if(annotation != null) {
            return annotation;
        }
        return null;
    }

    /**
     * 获取类名
     * @param declarName 全类名
     * @return 获取简化类名
     */
    public static String getSimpleClassName(String declarName){
        String name = "";
        //最后一个点，报名和类名的区分
        int index = declarName.lastIndexOf(".");
        if (index != -1) {
            name = declarName.substring(index + 1);
        }
        return name;
    }

    /**
     * 将类名首字母转小写
     * @param name 驼峰式命名规则的类名
     * @return 开头小写，符合驼峰命名的名称
     */
    public static String firstLetterToLowerCase(String name){
        String first = name.substring(0, 1);
        return first.toLowerCase()+name.substring(1);
    }

    /**
     * 获取传入对象get方法的键值（即公有属性）
     * @param obj 实体对象
     */
    public static Map<String,Object> getFieldAndValueFromEntity(Object obj){
        if (obj == null) {
            return null;
        }
        Class aClass = obj.getClass();
        Method[] methods = aClass.getMethods();
        Map<String,Object> map = new HashMap<>();
        //get 方法获取值
        try {
            for(Method m :methods){
                if(m.getName().contains("get")){
                    Method getMethod = aClass.getMethod(m.getName());
                    Object value = getMethod.invoke(obj);
                    //将对象属性和值存入map中
                    map.put(m.getName().replace("get",""),value);
                    System.out.println("获取的信息："+m.getName()+":"+value);
                }
            }
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 获取传入对象的所有属性(包括私有）的键值
     * @param obj 实体对象
     * @return 属性字段的所以键值
     */
    public static Map<String,Object> getDeclaredFieldAndValue(Object obj){
        if (obj == null) {
            return null;
        }
        Class aClass = obj.getClass();
        Map<String,Object> map = new HashMap<>();
        try {
            Field[] fields = aClass.getDeclaredFields();
            for(Field f : fields) {
                //这里要打开对私有属性的访问，不然报错
                f.setAccessible(true);
                Object value = f.get(obj);
                map.put(f.getName(), value);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return  map;
    }

    /**
     * 获取不知名对象的id值
     *这里是以默认的@id注解为标准找的
     * @param obj 对象
     * @return id值
     */
    public static Object getId(Object obj){
        Class<?> objClass = obj.getClass();
        Object id = null;
        //先根据@Id这个注解去找
        try {
            Field[] fields = objClass.getDeclaredFields();
//            for(Field field : fields){
//                field.setAccessible(true);
//                Object annoid = field.getAnnotation(LogField.class);
//                if(annoid != null && ((LogField) annoid).primaryKey()){
//                    id = field.get(obj);
//                    return id;
//                }
//            }
            //如果没有找，可能为id
//            if(id == null){
                Field field = objClass.getDeclaredField("id");
                //这里直接访问私有属性，打开权限
                field.setAccessible(true);
                id = field.get(obj);
                return id;
//            }
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        }
        return id;
    }

    /**
     * 判断是否属于基本类型
     * @param obj 对象
     * @return true：基本类型
     */
    public static boolean isBaseDefault(Object obj){
        return obj instanceof String || obj instanceof Integer || obj instanceof Double || obj instanceof Float
                || obj instanceof Byte || obj instanceof Long || obj instanceof Short || obj instanceof Character;
    }

    /**
     * 传入数据类型，判断是否是基本类型
     * @param type 对象类型
     * @return true：基本类型
     */
    public static boolean isBaseDefaultType(Class<?> type){
        return "java.lang.String".equals(type.getName()) || "java.lang.Integer".equals(type.getName()) ||
                "java.lang.Double".equals(type.getName()) || "java.lang.Float".equals(type.getName()) ||
                "java.lang.Byte".equals(type.getName()) || "java.lang.Long".equals(type.getName()) ||
                "java.Short".equals(type.getName());
    }

    /**
     * 根据传入的基本数据类型格式化数据
     * @param object 基本数据对象（没有类型的值）
     * @param type 数据类型
     */
    public static Object getBaseValueByType(Class<?> type,Object object){
        if ("java.lang.String".equals(type.getName())) {
            return object.toString();
        }
        if ("java.lang.Integer".equals(type.getName())) {
            return Integer.parseInt(object.toString());
        }
        if("java.lang.Double".equals(type.getName())) {
            return Double.parseDouble(object.toString());
        }
        if ("java.lang.Float".equals(type.getName())) {
            return Float.parseFloat(object.toString());
        }
        if("java.lang.Byte".equals(type.getName())) {
            return Byte.parseByte(object.toString());
        }
        if("java.lang.Long".equals(type.getName())) {
            return Long.parseLong(object.toString());
        }
        if("java.Short".equals(type.getName())) {
            return Short.parseShort(object.toString());
        }
        return null;
    }

    /**
     * 判断是否为基本类型的默认值
     * @param object 不知名对象
     * @return true：是基本类型默认值
     */
    public static boolean isBaseDefaultValue(Object object) {
        Class className = object.getClass();
        String strClassName = "" + className;
        if(className.equals(Integer.class)) {
            return (int)object == 0;
        } else if(className.equals(Byte.class)) {
            return (byte)object == 0;
        } else if(className.equals(Long.class)) {
            return (long)object == 0L;
        } else if(className.equals(Double.class)) {
            return (double)object == 0.0d;
        } else if(className.equals(Float.class)) {
            return (float)object == 0.0f;
        } else if(className.equals(Character.class)) {
            return (char)object == '\u0000';
        } else if(className.equals(Short.class)) {
            return (short)object == 0;
        } else if(className.equals(Boolean.class)) {
            return !((boolean) object);
        }
        return false;
    }

    /**
     * 通过setter、getter方法名获取属性名称
     *
     * @param methodName 方法名
     * @return 字段名
     */
    public static String getFieldNameForMethod(String methodName){
        String fieldName = "";
        if (methodName.startsWith("get")) {
            fieldName = methodName.replaceFirst("get","");
        }else if(methodName.startsWith("set")){
            fieldName = methodName.replaceFirst("set","");
        }
        return firstLetterToLowerCase(fieldName);
    }

    /**得到object对象正真的类型对象*/
    public static <T> T getActualField(Class<T> c,Object object){
        return (T)object;
    }

    public static Class<?> getActualClassType(Method method) throws ClassNotFoundException {
        Type type = method.getReturnType();
        if (type.equals(List.class)) {
            Type listType = method.getGenericReturnType();
            if (listType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) listType).getActualTypeArguments();
                //因为list泛型只有一个值 所以直接取0下标
                String typeName = actualTypeArguments[0].getTypeName();
                //真实返回值类型 Class对象
                return Class.forName(typeName);
            }
        }
        return null;
    }
}
